package impl

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/starmotioncf/common/third_game"
	"github.com/starmotioncf/common/third_game/baishun"
	"github.com/starmotioncf/common/third_game/joyplay"
	"github.com/starmotioncf/common/third_game/leadercc"
	"github.com/starmotioncf/common/third_game/reyou"
	"github.com/starmotioncf/soutchatinternal"
	"github.com/starmotioncf/soutchatinternal/constant"
	"github.com/starmotioncf/soutchatinternal/dto"
	"github.com/starmotioncf/soutchatinternal/repository"
	"github.com/starmotioncf/soutchatinternal/service"
	"strings"
	"sync"
	"time"
)

type thirdGameService struct {
	*service.Service
	gameProviders  map[string]third_game.Provider // 这个key就是 accountId
	jwtToken       *third_game.JWTToken
	thirdGameRepo  repository.ThirdGameRepository
	userRepo       repository.UserRepository
	countryRepo    repository.CountryRepository
	orderRepo      repository.OrderRepository
	accountRepo    repository.AccountRepository
	langRepo       repository.LangRepository
	drawWaterCache *sync.Map //抽水缓存
}

func NewThirdGameService(s *service.Service, conf service.ThirdGameConfig, thirdGameRepo repository.ThirdGameRepository,
	userRepo repository.UserRepository, countryRepo repository.CountryRepository,
	accountRepo repository.AccountRepository, orderRepo repository.OrderRepository, langRepo repository.LangRepository) service.ThirdGameService {
	_s := &thirdGameService{
		Service:       s,
		jwtToken:      third_game.NewJWTToken(conf.TokenSecretKey, conf.Issuer),
		thirdGameRepo: thirdGameRepo,
		userRepo:      userRepo,
		countryRepo:   countryRepo,
		orderRepo:     orderRepo,
		accountRepo:   accountRepo,
		langRepo:      langRepo,
		//thirdGame.PlatformCode 是代表一个厂商， appPlatform  是自定义的一个平台标志，有可能多个appPlatform 对应一个platformCode
		// appPlatform 对应着游戏链接的最后一个path
		gameProviders:  make(map[string]third_game.Provider),
		drawWaterCache: &sync.Map{},
	}
	//初始化第三方游戏实例
	_s.gameProviders = map[string]third_game.Provider{
		constant.ThirdGameAccountIdReyou:     reyou.NewReyou(constant.ThirdGameAccountIdReyou, _s),
		constant.ThirdGameAccountIdLeadercc:  leadercc.NewLeadercc(constant.ThirdGameAccountIdLeadercc, _s),
		constant.ThirdGameAccountIdBaishun:   baishun.NewBaiShunWithConfig(constant.ThirdGameAccountIdBaishun, conf.Baishun, _s),
		constant.ThirdGameAccountIdJoyplayEn: joyplay.NewJoyplay(constant.ThirdGameAccountIdJoyplayEn, conf.Joyplay, _s),
	}
	_s.init()
	return _s
}

func (s *thirdGameService) init() {
	//订阅游戏金币变化事件
	//s.eventBus.Subscribe(event2.ThirdGameGoldUpdateEvent, event3.ISubscribeFunc(s.createRecord))
	//s.eventBus.Subscribe(event2.ThirdGameGoldUpdateEvent, event3.ISubscribeFunc(s.soloGameRankScore))
}

// GetListV2 获取游戏列表
func (s *thirdGameService) GetList(ctx *gin.Context, req *dto.ThirdGameListReq) (res []*dto.ThirdGameCategoryList, err error) {
	list, err := s.getList(ctx, req)
	if err != nil {
		return nil, err
	}
	res = make([]*dto.ThirdGameCategoryList, 0)
	cateMap := make(map[constant.ThirdGameCategory]*dto.ThirdGameCategoryList)
	for i := range list {
		if v, ok := cateMap[list[i].Category]; ok {
			v.List = append(v.List, list[i])
		} else {
			_m := &dto.ThirdGameCategoryList{
				Type:  list[i].Category,
				Title: s.langRepo.Get(ctx, fmt.Sprintf("third_game.category_%d", list[i].Category)).TranslateTo(ctx.Request.Header.Get("lang")),
				List:  []*dto.ThirdGameListItem{list[i]},
			}
			cateMap[list[i].Category] = _m
			res = append(res, _m)
		}
	}
	return
}

// GetList 获取游戏列表
func (s *thirdGameService) getList(ctx *gin.Context, req *dto.ThirdGameListReq) (res []*dto.ThirdGameListItem, err error) {
	//根据区域获取游戏列表
	list, err := s.thirdGameRepo.GetListByRegion(ctx, internal.GetRegionFromCtx(ctx))
	if err != nil {
		return
	}
	uid := internal.GetUidFromCtx(ctx)
	res = make([]*dto.ThirdGameListItem, 0)
	filterEntity := internal.GetFilterEntityFromCtx(ctx)
	lang := ctx.Request.Header.Get("lang")
	for _, v := range list {
		if !v.Filter.Verify(filterEntity) {
			continue
		}
		plat, _err := s.GetPlatformProvider(v.PlatformCode)
		if _err != nil {
			continue
		}
		var token string
		if token, _err = plat.GetToken(ctx, uid, time.Second*86400); _err != nil {
			continue
		}
		//替换参数
		repLink := strings.NewReplacer(
			"{uid}", fmt.Sprintf("%d", uid),
			"{lang}", plat.GetLang(lang),
			"{rid}", fmt.Sprintf("%d", req.Rid), //房间id
			"{time}", fmt.Sprintf("%d", time.Now().UnixMilli()),
			"{timestamp}", fmt.Sprintf("%d", time.Now().Unix()),
			"{token}", token,
			"{thirdGameId}", v.GameId, //第三方游戏id
			"{gameId}", fmt.Sprintf("%d", v.Id), //内部游戏id
			"{platform}", string(plat.Platform()),
			"{accountId}", plat.AccountId(),
		)
		item := dto.ThirdGameListItem{
			Id:       v.Id,
			Icon:     v.Icon,
			Link:     repLink.Replace(v.Link),
			Image:    v.Image,
			Height:   v.Height,
			Name:     v.Name.Get(lang),
			IsHot:    v.Hot,
			Category: v.Category,
		}
		res = append(res, &item)
	}
	return res, nil
}

// GetPlatformProvider 获取支持的第三方游戏平台的一个实例
func (s *thirdGameService) GetPlatformProvider(appId string) (third_game.Provider, error) {
	if plat, ok := s.gameProviders[appId]; ok {
		return plat, nil
	}
	return nil, fmt.Errorf("not support the platform appid[%s]", appId)
}
